% this file is to use with the t.pl that has constraint about consistent GE. 

claLength(startNode,ClaEICoverage,0):-!.
claLength(endNode-EITIs,ClaEICoverage,0):-!.
claLength(ClaID,ClaEICoverage,ClaDescriptionLength):-
	ClaID=[rs-{ReactionID,LimitingType,HypothesizedState,Time}],
	scoreByGEData({ReactionID,LimitingType,HypothesizedState,Time},ClaEICoverage,Score_GE),
	ClaDescriptionLength=Score_GE.


% no degree, but simply agree or not
% agree -- no description score%enzymlimiting,cataIncreased,
% not agree -- 2
% not annotated or not measured -- 1

% when enzyme limiting, it is the same as before
scoreByGEData({ReactionID,enzymeLimiting,HypothesizedState,MutantTypeTime},ClaEICoverage,Score):-
	catalyzed_by_ECclass(ReactionID,EC_Number),
	MutantTypeTime=DoseTime, %timeEquivenlent(Time,DoseTime), cancer also need to take care of the following DoseTime.
	concentration_e(EC_Number,GEChange,Degree,DoseTime),!, 	
	sepMutantTypeTime(MutantTypeTime,MutantType,Time),

	%Scale_byTime=1, %
	compute_MetsGE_consistentDegree_AlongTime(MutantType,ClaEICoverage,EC_Number,Scale_byTime),	
	compute_MetsGE_consistentDegree_acrossMutants(Time,ClaEICoverage,EC_Number,Scale_byDiffMutants),			
	Score=10*Scale_byTime*Scale_byDiffMutants.


% EIs is for the degree of coverage
compute_MetsGE_consistentDegree_acrossMutants(Time,EIs,EC_Number,Scale):-
	maplist(compute_eachMetGE_consistentDegree_acrossMutants({Time,EC_Number}),EIs,ConsistentDegrees),
	multiplyList(ConsistentDegrees,Scale).	

% no worry which type are you using as a seed, but the one with similar changes -- do you need to know itself, yes--itself set up the standard to be the same or opposite
compute_eachMetGE_consistentDegree_acrossMutants({Time,EC_Number},EI,ConsistentDegree):-
	getMETChangesAcrossMutants(Time,EI,Met_ChangesAcrossMutants),
	getGEChangesAcrossMutants(Time,EC_Number,GE_ChangesAcrossMutants),
	(consistentMetGE(Met_ChangesAcrossMutants,GE_ChangesAcrossMutants)->
		ConsistentDegree is 1;
		((\+sameList(Met_ChangesAcrossMutants),mutantPartialConsistent(Met_ChangesAcrossMutants,GE_ChangesAcrossMutants))->
			ConsistentDegree is 1;
			ConsistentDegree=3
		)
	).



% **** need to say -- those no_change case -- it doesn't matter they are not propotional 

% for those the same change, yes, while for the one that change, its GE may keep the same -- which make it not proportional to it is changed MET. In this case, its 
mutantPartialConsistent([MET_CNR,MET_NOR,MET_RIN],[GE_CNR,GE_NOR,GE_RIN]):-
	MET_CNR=MET_NOR, GE_CNR=GE_NOR. % RIN one is not propotional
mutantPartialConsistent([MET_CNR,MET_NOR,MET_RIN],[GE_CNR,GE_NOR,GE_RIN]):-
	MET_NOR=MET_RIN, GE_NOR=GE_RIN.
mutantPartialConsistent([MET_CNR,MET_NOR,MET_RIN],[GE_CNR,GE_NOR,GE_RIN]):-
	MET_CNR=MET_RIN,GE_CNR=GE_RIN.


mutantPartialConsistent([MetChange_Late,no_change,no_change],[GE_Early,GE_Mid,GE_Late]):-!. 
mutantPartialConsistent([no_change,MetChange_Late,no_change],[GE_Early,GE_Mid,GE_Late]):-!. 
mutantPartialConsistent([no_change,no_change,MetChange_Late],[GE_Early,GE_Mid,GE_Late]):-!. %,GE_Early\==GE_Late,GE_Mid\==GE_Late. 
											    %It doesn't have to be change -- may keep the same, while the other has sth else to regulate and balance. 
mutantPartialConsistent([no_change,MetChange_Mid,MetChange_Late],[GE_Early,GE_Mid,GE_Late]):-
		GE_Early\==GE_Mid,
		pair([MetChange_Mid,MetChange_Late],[GE_Mid,GE_Late]).
mutantPartialConsistent([MetChange_Early,no_change,MetChange_Late],[GE_Early,GE_Mid,GE_Late]):-
		GE_Early\==GE_Mid, %GE_Mid\==GE_Late, -- no need, since you require them to be the same
		pair([MetChange_Early,MetChange_Late],[GE_Early,GE_Late]).
mutantPartialConsistent([MetChange_Early,MetChange_Late,no_change],[GE_Early,GE_Late,GE_Mid]):-
		GE_Early\==GE_Mid, %GE_Mid\==GE_Late, -- no need, since you require them to be the same
		pair([MetChange_Early,MetChange_Late],[GE_Early,GE_Late]).

% if Met same change, then they required to be the same
% only penalize when it is same change, while different GE.
pair([Met1,Met2],[GE1,GE2]):-
	Met1==Met2,!,GE1=GE2.
pair([Met1,Met2],[GE1,GE2]).% One Met no_change, while the rest two again diffrent -> that is the case that three value for one Met % threonine late stage
 



sepMutantTypeTime(MutantTypeTime,MutantType,Time):-
	atom_chars(MutantTypeTime,[A,B,C,D,E]),atom_chars(MutantType,[A,B,C]),atom_chars(Time,[E]).
assembleMutantTypeTime(MutantType,Time,MutantTypeTime):-
	atom_chars(MutantType,[A,B,C]),atom_chars(Time,[E]),atom_chars(MutantTypeTime,[A,B,C,'_',E]).


getMETChangesAcrossMutants(Time,EI,Met_ChangesAcrossMutants):-
	getAllMutants(AllMutants),maplist(assembleMutantTypeTime,AllMutants,[Time,Time,Time],MutantTypeTimes),
	ex0(EI,concentration(MetName,Change,Degree,EI_MutantTypeTime),1),
	maplist(getMetChange_fromEI(MetName),MutantTypeTimes,Met_ChangesAcrossMutants).

getMetChange_fromEI(MetName,MutantTypeTime,Met_Change):-
	ex0(EI,concentration(MetName,Met_Change,Degree,MutantTypeTime),1).

getGEChangesAcrossMutants(Time,EC_Number,GE_ChangesAcrossMutants):-
	getAllMutants(AllMutants),maplist(assembleMutantTypeTime,AllMutants,[Time,Time,Time],MutantTypeTimes),
	maplist(getGEChange(EC_Number),MutantTypeTimes,GE_ChangesAcrossMutants).

getGEChange(EC_Number,MutantTypeTime,Change):-
	concentration_e(EC_Number,Change,Degree,MutantTypeTime).
	


compute_MetsGE_consistentDegree_AlongTime(MutantType,EIs,EC_Number,Scale):-
	maplist(compute_eachMetGE_consistentDegree_AlongTime({MutantType,EC_Number}),EIs,ConsistentDegrees),
	multiplyList(ConsistentDegrees,Scale).	

compute_eachMetGE_consistentDegree_AlongTime({MutantType,EC_Number},EI,ConsistentDegree):-
	getMETChangesAlongTime(EI,Met_ChangesAlongTime),
	getGEChangesAlongTime(MutantType,EC_Number,GE_ChangesAlongTime),
	(consistentMetGE(Met_ChangesAlongTime,GE_ChangesAlongTime)->
		ConsistentDegree is 1;
		((\+sameList(Met_ChangesAlongTime),partialConsistentMetGE(Met_ChangesAlongTime,GE_ChangesAlongTime))->
			ConsistentDegree is 1;
			ConsistentDegree=3
		)
	).
%change at the same point -- when it is no Change it is difficult to ask no change as well, but the one *change* (rather simply not the same)

partialConsistentMetGE([MetChange_Late,no_change,no_change],[GE_Early,GE_Mid,GE_Late]):-!,GE_Early\==GE_Mid,GE_Early\==GE_Late.
partialConsistentMetGE([no_change,MetChange_Late,no_change],[GE_Early,GE_Mid,GE_Late]):-!,GE_Early\==GE_Mid,GE_Mid\==GE_Late.
partialConsistentMetGE([no_change,no_change,MetChange_Late],[GE_Early,GE_Mid,GE_Late]):-!,GE_Early\==GE_Late,GE_Mid\==GE_Late.
partialConsistentMetGE([no_change,MetChange_Mid,MetChange_Late],[GE_Early,GE_Mid,GE_Late]):-
		GE_Early\==GE_Mid,
		consistentMetGE([MetChange_Mid,MetChange_Late],[GE_Mid,GE_Late]).
partialConsistentMetGE([MetChange_Early,no_change,MetChange_Late],[GE_Early,GE_Mid,GE_Late]):-
		GE_Early\==GE_Mid, %GE_Mid\==GE_Late, -- no need, since you require them to be the same
		consistentMetGE([MetChange_Early,MetChange_Late],[GE_Early,GE_Late]).

consistentMetGE(MetChangesAlongTime,GEChangesAlongTime):-
	maplist(propotionalChange,MetChangesAlongTime,GEChangesAlongTime).
consistentMetGE(MetChangesAlongTime,GEChangesAlongTime):-
	maplist(oppositeChange,MetChangesAlongTime,GEChangesAlongTime).

% similar to the propotionalBelow, but that is the reaciton state with GE.
propotionalChange(up,up).
propotionalChange(no_change,noChange).
propotionalChange(down,down).

oppostieChange(up,down).
oppostieChange(no_change,noChange).
oppostieChange(down,up).



getMETChangesAlongTime(EI_late,[Change_E,Change_M,Change_L]):-
	EI_early is EI_late-22,
	EI_mid is EI_late+22,
	ex0(EI_early,concentration(M_Name,Change_E,Degree1,Early),1),
	ex0(EI_mid,concentration(M_Name,Change_M,Degree2,Mid),1),
	ex0(EI_late,concentration(M_Name,Change_L,Degree3,Late),1).

getGEChangesAlongTime(MutantType,EC_Number,[Change_E,Change_M,Change_L]):-
	getAllTimePoints(MutantType,[Early,Mid,Late]),
	concentration_e(EC_Number,Change_E,Degree1,Early),
	concentration_e(EC_Number,Change_M,Degree2,Mid),
	concentration_e(EC_Number,Change_L,Degree3,Late).

getMutantType('CNR_E','CNR').
getMutantType('NOR_E','NOR').
getMutantType('RIN_E','RIN').
getMutantType('CNR_M','CNR').
getMutantType('NOR_M','NOR').
getMutantType('RIN_M','RIN').
getMutantType('CNR_L','CNR').
getMutantType('NOR_L','NOR').
getMutantType('RIN_L','RIN').

getOtherMutantTypes('CNR_L',['NOR_L','RIN_L']).
getOtherMutantTypes('NOR_L',['CNR_L','RIN_L']).
getOtherMutantTypes('RIN_L',['CNR_L','NOR_L']).

getAllTimePoints('CNR',['CNR_E','CNR_M','CNR_L']).
getAllTimePoints('NOR',['NOR_E','NOR_M','NOR_L']).
getAllTimePoints('RIN',['RIN_E','RIN_M','RIN_L']).


getAllMutants(['CNR','NOR','RIN']).



scoreByGEData({ReactionID,substrateLimiting,HypothesizedState,Time},ClaEICoverage,Score):-
	catalyzed_by_ECclass(ReactionID,EC_Number),
	Time=DoseTime, %timeEquivenlent(Time,DoseTime),
	concentration_e(EC_Number,GEChange,Degree,DoseTime),!,
	(nonContradict(HypothesizedState,GEChange)->
		Score=1;
		Score=3		
	).






/*	
getMutantType(Time,MutantType),
compute_nonRegulatorDegree_AlongTime(MutantType,EC_Number,HypothesizedState,NonRegulatorDegree),		
	Score=1*NonRegulatorDegree.
*/



compute_nonRegulatorDegree_AlongTime(MutantType,EC_Number,HypothesizedState,NonRegulatorDegree):-
	getAllTimePoints(MutantType,[Early,Mid,Late]),
	concentration_e(EC_Number,Change_E,Degree1,Early),
	concentration_e(EC_Number,Change_M,Degree2,Mid),
	concentration_e(EC_Number,Change_L,Degree3,Late),
	maplist(compute_nonRegulatorDegree(HypothesizedState),[Change_E,Change_M,Change_L],[DE,DM,DL]),
	NonRegulatorDegree is DE*DE*DM*DL. % early stage has higer effect


compute_nonRegulatorDegree(HypothesizedState,noChange,0.5):-!.
compute_nonRegulatorDegree(HypothesizedState,GEChange,1):-
	nonContradict(HypothesizedState,GEChange),!.
compute_nonRegulatorDegree(HypothesizedState,GEChange,2):-!.



% let's not to look at unknown for now
scoreByGEData({ReactionID,enzymeLimiting,HypothesizedState,Time},EIs,Score):- 
	length(EIs,NumEI), Score is 400/NumEI.
scoreByGEData({ReactionID,substrateLimiting,HypothesizedState,Time},EIs,Score):-
	%length(EIs,NumEI), Score is 4/NumEI.
	Score=2.


proportional(cataIncreased,up).
proportional(cataDecreased,down).
proportional(cataNoChange,noChange).


nonContradict(sUp,GEChange):- GEChange\==down.
nonContradict(sDown,GEChange):- GEChange\==up.
nonContradict(sNoChange,GEChange):- GEChange=='noChange'.



/*
1. Enzyme Limiting is more expensive then substrate limiting. 
For two alternatives, when their enzyme limiting reactions has the same score, and their substrate limiting reaction differentiate them out. 

substrate limiting still counts for DL -- make the shorter explanation/closer effect more preferable


2. The unknown is double, this gives it a chance to beat those known. 

3. the Shared number is taken into account, this is reasonable from information theory point -- more frequent one are given shorter DL.

4. noContradict constrain for substrateLimiting, is this reasonable? --- that's more appropriate for early stage, So can you refer to the early stage to differentiate them

*/